package jtg;

import soot.Unit;
import soot.jimple.internal.JAssignStmt;
import soot.jimple.internal.JIfStmt;
import soot.jimple.internal.JReturnStmt;
import soot.toolkits.graph.UnitGraph;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class DataFlowPath {
    public DirectedGraph dg;
    public UnitGraph ug;
    public DataFlowGraph df;

    public DataFlowPath(DirectedGraph dg,UnitGraph ug) {
        this.dg = dg;
        this.ug = ug;
        deal();
    }

    public void deal()
    {
        df=new DataFlowGraph();
        for (Unit s : ug) {
            if (s.toString().contains(":=")) {
                String var = s.toString().split(":=")[0].trim();
                df.addDef(var);
                df.addd(s,var,df.def,dg);
                continue;
            }
            if (s instanceof JAssignStmt) {
                String left = ((JAssignStmt) s).getLeftOp().toString();
                String right = ((JAssignStmt) s).getRightOp().toString();
                if (!df.def.contains(left)) {
                    df.addDef(left);
                    df.addd(s,left,df.def,dg);
                }else {
                    df.addd(s,left,df.def,dg);
                }
                for(String l:df.def)
                {
                    if(right.contains(l))
                    {
                        df.addu(s,l,df.def,dg);
                    }
                }
                continue;
            }
            if (s instanceof JIfStmt) {
                String ifstms = ((JIfStmt) s).getCondition().toString();
                for ( String l : df.def) {
                    if (ifstms.contains(l)) {
                        df.addu(s,l,df.def,dg);
                    }
                }
                continue;
            }
            if (s instanceof JReturnStmt) {
                String rtstms = s.toString().replace("return", "").trim();
                for ( String l : df.def) {
                    if (rtstms.contains(l)) {
                        df.addu(s,l,df.def,dg);
                    }
                }
            }
        }
    }
    private void DFS1(Unit start, Unit end, DirectedGraph dg, List<Unit> path, List<Unit> ret) {
        if (start.equals(end)) {
            ret.addAll(path);
            return;
        }

        for (Unit t : dg.tail) {
            if (start.equals(t)) {
                path.add(start);
                return;
            }
        }
        path.add(start);

        for (int i = 0; i < dg.n; ++i) {
            if (dg.edge[dg.vertex.indexOf(start)][i]) {
                DFS1(dg.vertex.get(i), end, dg, path, ret);
                path.remove(path.size() - 1);
            }
        }
    }
    public List<List<Unit>>  calDuPath(int[][]d,int[][]u)
    {
        List<List<Unit>> dupath = new ArrayList<>();
        for(int i=0;i<d.length;++i)
            for(int j=0;j<d[i].length;++j)
            {
                if(d[i][j]==1)
                {
                    for(int k=0;k<u.length;++k)
                    {
                        if(u[k][j]==1) {
                            List<Unit> path = new ArrayList<>();
                            List<Unit> ret = new ArrayList<>();
                            DFS1(dg.vertex.get(i), dg.vertex.get(k), dg, path, ret);
                            if(!ret.isEmpty())
                                ret.add(dg.vertex.get(k));
                            dupath.add(ret);
                        }
                    }
                }
            }
        return dupath;
    }
}
